package com.dwms.utils;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import com.dwms.constant.HeaderConstants;
import com.dwms.entity.Result;
import com.dwms.enums.ResultCode;
import com.dwms.enums.SourceType;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.util.Date;

/**
 * 签名工具
 */
@Slf4j
public class SignUtil {

    private static final String contentEncoding = "UTF-8";

    private static final String ADMIN_WEB_KEY = "6S29DK19ts5EJ82LTd4RecdXxv4Ch06D";

    // 通用签名密钥
    public static final String COMMON_SIGN_KEY = "670kj1OEY0oQzUE1pkGC015praSI4j6z";


    /**
     * 接口签名校验
     *
     * @param request
     * @return
     */
    public static Result checkSign(String[] ignoreChecks, String requestUri, HttpServletRequest request) {
        if (StringUtils.isEmpty(requestUri)) {
            return Result.success();
        }
        String sign = request.getHeader(HeaderConstants.SIGN);
        if (COMMON_SIGN_KEY.equals(sign)) {
            return Result.success();
        }
        boolean ignoreSign = false;
        for (String reqURI : ignoreChecks) {
            if (requestUri.contains(reqURI)) {
                ignoreSign = true;
                break;
            }
        }
        if (ignoreSign) {
            return Result.success();
        }
        if (StrUtil.isEmpty(sign)) {
            return Result.failed(ResultCode.FAIL_BUSINESS, "签名参数错误");
        }
        String source = request.getHeader(HeaderConstants.SOURCE);
        String timestamp = request.getHeader(HeaderConstants.TIME_STAMP);
        String randomId = request.getHeader(HeaderConstants.RANDOM_ID);
        //2、校验请求是否已过期
        if (timestamp == null) {
            return Result.failed(ResultCode.PARAM_IS_BLANK);
        }
        Date deviceDate = DateUtil.date(Long.parseLong(timestamp));
        Date localDate = DateUtil.date();
        long time = DateUtil.between(deviceDate, localDate, DateUnit.MINUTE);
        //时间相差5分钟为过期
        if (time > 5) {
            log.info("客户端时间为：{},服务器时间为{}", deviceDate, localDate);
            return Result.failed(ResultCode.PARAM_IS_INVALID, "签名信息已过期");
        }
        //3、校验签名信息是否正确： Base64(md5(PUBLIC_KEY+app_key+time_stamp))
        String publicKey = "";

        if (SourceType.ADMIN_WEB.getCode().equals(source)) {
            publicKey = ADMIN_WEB_KEY;
        }

        if (StrUtil.isEmpty(randomId)) {
            return Result.failed(ResultCode.PARAM_IS_INVALID, "签名参数错误");
        }
        String preMsd5 = publicKey + CommonUtils.clearNull(source) + timestamp + CommonUtils.clearNull(randomId);
        String afterMd5 = SecureUtil.md5(preMsd5);
        String localSign = Base64.encode(afterMd5);
        //忽略大小写
        if (!sign.equalsIgnoreCase(localSign)) {
            log.info("md5前pre_msd5：{}", preMsd5);
            log.info("md5后after_md5：{}", afterMd5);
            log.info("后端签名信息local_sign：{}", localSign);
            log.info("app签名信息app_sign：{}", sign);
            return Result.failed(ResultCode.ACCESS_UNAUTHORIZED, "签名校验失败");
        }
        return Result.success();
    }
}
